﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using AutoItX3Lib;
using CommonFunction;
using System.Runtime.InteropServices;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Security.Permissions;

namespace Pokerist_BuyAndSell
{
    [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
    public partial class PokeristBSMain : Form
    {
        CancellationTokenSource tokenSource = null;
        Task taskPlayGame = null;

        public PokeristBSMain()
        {
            InitializeComponent();

            Pokerist_BS_Common.GameStatus = Pokerist_BS_Common.GAME_STATUS.LOGIN;

            InitForm();
        }

        private void btnPlayGame_Click(object sender, EventArgs e)
        {
            if (!ValidateBeforePlay())
            {
                MessageBox.Show("the Poker " + txtPokerName.Text.ToUpper() + " is in the game. Please enter another name of the poker", "Pokerist warning", MessageBoxButtons.OK);
                txtPokerName.Clear();
                txtPokerName.Focus();
                return;
            }

            var formLogin = this.BrowserGame.Document.Forms[0];
            formLogin.GetElementsByTagName("input").GetElementsByName("PokeristSignInForm[login]")[0].InnerText = txtEmail.Text;
            formLogin.GetElementsByTagName("input").GetElementsByName("PokeristSignInForm[password]")[0].InnerText = txtPassword.Text;

            formLogin.InvokeMember("submit");
            grpConfiguration.Enabled = false;

            AccessData pokerData = new AccessData();
            var data = pokerData.GetData_Pokerist_BS();
            data.SetPokerName(txtPokerName.Text);
            data.SetPokerEmail(txtEmail.Text);
            data.SetPokerPassword(txtPassword.Text);
            
            pokerData.SaveData_Pokerist_BS(data);
            pokerData = null;

            this.Text = string.Format("Pokerist - {0}", txtPokerName.Text);
            Pokerist_BS_Common.PokerTitle = this.Text;

            Pokerist_BS_Common.GameStatus = Pokerist_BS_Common.GAME_STATUS.LOGIN;            
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;

            AccessData pokerData = new AccessData();
            var data = pokerData.GetData_Pokerist_BS();
            data.SetPokerRole(radBuy.Checked ? 1 : 2);
            
            pokerData.SaveData_Pokerist_BS(data);
            pokerData = null;

            this.Text = string.Format("Pokerist - {0}", txtPokerName.Text);
            Pokerist_BS_Common.PokerTitle = this.Text;
            btnStart.Text = "&Resume";

            Pokerist_BS_Common.GameStatus = Pokerist_BS_Common.GAME_STATUS.PLAY;
            Pokerist_BS_Common.GAME_DELAY = Convert.ToInt32(txtDelay.Text);
            Pokerist_BS_Common.Poker_Role = radBuy.Checked ? Pokerist_BS_Common.ROLES.BUY : Pokerist_BS_Common.ROLES.SALE;

            SwitchStatusControls();

            tokenSource = new CancellationTokenSource();
            Action playGame = delegate() { this.PlayGame(); };
            taskPlayGame = new Task(playGame, tokenSource.Token);

            taskPlayGame.Start();

            this.Cursor = Cursors.Default;
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            var confirm = MessageBox.Show("Do you want to STOP the Pokerist ?", "Pokerist Confirm", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1);
            if (confirm != System.Windows.Forms.DialogResult.Yes) return;

            this.Cursor = Cursors.WaitCursor;

            Pokerist_BS_Common.GameStatus = Pokerist_BS_Common.GAME_STATUS.PAUSE;
            tokenSource.Cancel();
            tokenSource = null;
            taskPlayGame = null;

            SwitchStatusControls();

            this.Cursor = Cursors.Default;
        }

        #region "Play game"

        private bool ValidateBeforePlay()
        {
            if (string.IsNullOrEmpty(txtPokerName.Text.Trim())) return false;

            AutoItX3 autoit = new AutoItX3();
            var winExist = autoit.WinExists(string.Format("Pokerist - {0}", txtPokerName.Text.Trim()));

            autoit = null;
            return (winExist == 0);
        }

        private void PlayGame()
        {
            //var counter = 0;
            //var isReduce = false;

            while (Pokerist_BS_Common.GameStatus == Pokerist_BS_Common.GAME_STATUS.PLAY)
            {
                DoBuy();
                //if (Pokerist_BS_Common.Poker_Role == Pokerist_BS_Common.ROLES.BUY)
                //{
                //    DoBuy();
                //}
                //else
                //{
                //    DoSale();
                //}
                //counter++;

                //if (counter > Pokerist_BS_Common.GAME_COUNTER)
                //{
                //    isReduce = true;
                //    break;
                //}

                //System.Threading.Thread.Sleep(Pokerist_BS_Common.GAME_DELAY);
            }

            //if (isReduce)
            //{
            //    ReduceCPU();
            //}
        }

        private void InitForm()
        {   
            Pokerist_BS_Common.Data_FilePath = Path.Combine(Application.StartupPath, @"Data\DataConfig.xml");
            Pokerist_BS_Common.icon_Profile_FilePath = Path.Combine(Application.StartupPath, @"Data\profile.jpg");
            Pokerist_BS_Common.icon_Profile_Result_FilePath = Path.Combine(Application.StartupPath, @"Data\tempProfile.jpg");

            Pokerist_BS_Common.HANDLER = this.BrowserGame.Handle;
            Pokerist_BS_Common.TIME_STOP = null;

            AccessData data = new AccessData();
            var pokerData = data.GetData_Pokerist_BS();

            txtPokerName.Text = pokerData.GetPokerName();
            txtEmail.Text = pokerData.GetPokerEmail();
            txtPassword.Text = pokerData.GetPokerPassword();

            int pokerRole = pokerData.GetPokerRole();
            if (pokerRole == 1)
            {
                radBuy.Checked = true;
                radSale.Checked = false;
            }
            else
            {
                radBuy.Checked = false;
                radSale.Checked = true;
            }

            data = null;
        }

        private void DoBuy()
        {
            AutoItX3 autoit = new AutoItX3();

            //click clear windows
            autoit.ControlClick(Pokerist_BS_Common.PokerTitle, "", "[CLASS:Internet Explorer_Server; INSTANCE:1]", "LEFT", 5, Pokerist_BS_Common.CLEAR_POS_X, Pokerist_BS_Common.CLEAR_POS_Y);
            
            //click profile
            autoit.ControlClick(Pokerist_BS_Common.PokerTitle, "", "[CLASS:Internet Explorer_Server; INSTANCE:1]", "LEFT", 1, Pokerist_BS_Common.BUY_PROFILE_POS_X, Pokerist_BS_Common.BUY_PROFILE_POS_Y);
            while (!IsProfile())
            {
                autoit.Sleep(Pokerist_BS_Common.GAME_DELAY);
            }

            //click buy button
            autoit.ControlClick(Pokerist_BS_Common.PokerTitle, "", "[CLASS:Internet Explorer_Server; INSTANCE:1]", "LEFT", 1, Pokerist_BS_Common.BUY_ICON_POS_X, Pokerist_BS_Common.BUY_ICON_POS_Y);
            
            //click transport button
            autoit.ControlClick(Pokerist_BS_Common.PokerTitle, "", "[CLASS:Internet Explorer_Server; INSTANCE:1]", "LEFT", 1, Pokerist_BS_Common.BUY_TRANSPORT_POS_X, Pokerist_BS_Common.BUY_TRANSPORT_POS_Y);
            
            //click luxury button
            autoit.ControlClick(Pokerist_BS_Common.PokerTitle, "", "[CLASS:Internet Explorer_Server; INSTANCE:1]", "LEFT", 1, Pokerist_BS_Common.BUY_LUXURY_POS_X, Pokerist_BS_Common.BUY_LUXURY_POS_Y);
            
            //click bicycle button
            //autoit.ControlClick(Pokerist_BS_Common.PokerTitle, "", "[CLASS:Internet Explorer_Server; INSTANCE:1]", "LEFT", 1, Pokerist_BS_Common.BUY_BICYCLE_POS_X, Pokerist_BS_Common.BUY_BICYCLE_POS_Y);

            //click buy transport button
            autoit.ControlClick(Pokerist_BS_Common.PokerTitle, "", "[CLASS:Internet Explorer_Server; INSTANCE:1]", "LEFT", 1, Pokerist_BS_Common.BUY_TRANBUY_POS_X, Pokerist_BS_Common.BUY_TRANBUY_POS_Y);
            //autoit.Sleep(500);

            //click OK confirm button
            autoit.ControlClick(Pokerist_BS_Common.PokerTitle, "", "[CLASS:Internet Explorer_Server; INSTANCE:1]", "LEFT", 1, Pokerist_BS_Common.BUY_OK_POS_X, Pokerist_BS_Common.BUY_OK_POS_Y);

            //click clear windows
            autoit.ControlClick(Pokerist_BS_Common.PokerTitle, "", "[CLASS:Internet Explorer_Server; INSTANCE:1]", "LEFT", 5, Pokerist_BS_Common.CLEAR_POS_X, Pokerist_BS_Common.CLEAR_POS_Y);

            autoit = null;
        }

        private bool IsProfile()
        {
            if (!File.Exists(Pokerist_BS_Common.icon_Profile_FilePath)) return false;

            var imgCheck = (Bitmap)Bitmap.FromFile(Pokerist_BS_Common.icon_Profile_FilePath);
            if (imgCheck == null) return false;

            var imgResult = CaptureImage(Pokerist_BS_Common.HANDLER, Pokerist_BS_Common.IMG_PROFILE_POS_X, Pokerist_BS_Common.IMG_PROFILE_POS_Y, Pokerist_BS_Common.IMG_PROFILE_WIDTH, Pokerist_BS_Common.IMG_PROFILE_HEIGH);
            imgResult.Save(Pokerist_BS_Common.icon_Profile_Result_FilePath);
            imgResult.Dispose();

            imgResult = Image.FromFile(Pokerist_BS_Common.icon_Profile_Result_FilePath);

            var compare = imgCheck.EqualTo(imgResult);

            imgResult.Dispose();
            imgCheck.Dispose();

            return compare;
        }

        private void DoSale()
        {
            AutoItX3 autoit = new AutoItX3();

            //click profile
            autoit.ControlClick(Pokerist_BS_Common.PokerTitle, "", "[CLASS:Internet Explorer_Server; INSTANCE:1]", "LEFT", 1, Pokerist_BS_Common.BUY_PROFILE_POS_X, Pokerist_BS_Common.BUY_PROFILE_POS_Y);
            autoit.Sleep(100);

            //click property button
            autoit.ControlClick(Pokerist_BS_Common.PokerTitle, "", "[CLASS:Internet Explorer_Server; INSTANCE:1]", "LEFT", 1, Pokerist_BS_Common.SALE_PROPERTY_POS_X, Pokerist_BS_Common.SALE_PROPERTY_POS_Y);
            autoit.Sleep(500);

            //click first item
            autoit.ControlClick(Pokerist_BS_Common.PokerTitle, "", "[CLASS:Internet Explorer_Server; INSTANCE:1]", "LEFT", 1, Pokerist_BS_Common.SALE_ITEM_POS_X, Pokerist_BS_Common.SALE_ITEM_POS_Y);
            autoit.Sleep(500);

            //click OK confirm button
            autoit.ControlClick(Pokerist_BS_Common.PokerTitle, "", "[CLASS:Internet Explorer_Server; INSTANCE:1]", "LEFT", 1, Pokerist_BS_Common.SALE_OK_POS_X, Pokerist_BS_Common.SALE_OK_POS_Y);

            autoit = null;
        }

        private void ReduceCPU()
        {
            Pokerist_BS_Common.GameStatus = Pokerist_BS_Common.GAME_STATUS.PAUSE;

            tokenSource.Cancel();
            tokenSource = null;
            taskPlayGame = null;

            Pokerist_BS_Common.TIME_STOP = DateTime.Now;
        }

        private void ResumeThread()
        {
            Pokerist_BS_Common.TIME_STOP = null;

            Pokerist_BS_Common.GameStatus = Pokerist_BS_Common.GAME_STATUS.PLAY;
            
            tokenSource = new CancellationTokenSource();
            Action playGame = delegate() { this.PlayGame(); };
            taskPlayGame = new Task(playGame, tokenSource.Token);
            taskPlayGame.Start();
        }

        #endregion

        #region "controls behaviours"

        private void SwitchStatusControls()
        {
            this.BrowserGame.Document.Window.ScrollTo(this.BrowserGame.Left, this.BrowserGame.Top + 320);

            if (Pokerist_BS_Common.GameStatus != Pokerist_BS_Common.GAME_STATUS.PLAY)
            {
                setEnableButton(btnStart, true);
                setEnableButton(btnStop, false);
                setEnableGroup(grpGamePlay, true);                
            }
            else
            {
                setEnableButton(btnStart, false);
                setEnableButton(btnStop, true);
                setEnableGroup(grpGamePlay, false);
            }
        }

        delegate void SetEnableButtonCallback(Button btn, bool isEnabled);
        private void setEnableButton(Button btn, bool isEnabled)
        {
            if (btn.InvokeRequired)
            {
                SetEnableButtonCallback setEnabled = new SetEnableButtonCallback(setEnableButton);
                this.Invoke(setEnabled, btn, isEnabled);
            }
            else
                btn.Enabled = isEnabled;
        }

        delegate void SetEnableGroupCallback(GroupBox grp, bool isEnabled);
        private void setEnableGroup(GroupBox grp, bool isEnabled)
        {
            if (grp.InvokeRequired)
            {
                SetEnableGroupCallback setEnabled = new SetEnableGroupCallback(setEnableGroup);
                this.Invoke(setEnabled, grp, isEnabled);
            }
            else
                grp.Enabled = isEnabled;
        }

        #endregion

        private void button1_Click(object sender, EventArgs e)
        {
            this.BrowserGame.Document.Window.ScrollTo(this.BrowserGame.Left, this.BrowserGame.Top + Convert.ToInt32(textBox5.Text));
            //DoBuy();
            //var image = CaptureImage(this.BrowserGame.Handle, Convert.ToInt32(textBox1.Text), Convert.ToInt32(textBox2.Text),
            //    Convert.ToInt32(textBox3.Text), Convert.ToInt32(textBox4.Text));

            //string path = Path.Combine(Application.StartupPath, @"Data\temp.jpg");

            //image.Save(path, System.Drawing.Imaging.ImageFormat.Jpeg);

            //image.Dispose();
        }

        #region "proccess images"

        [DllImport("user32.dll")]
        public static extern IntPtr GetWindowDC(IntPtr hWnd);
        [DllImport("gdi32.dll")]
        public static extern bool BitBlt(IntPtr hObject, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hObjectSource, int nXSrc, int nYSrc, int dwRop);
        [DllImport("gdi32.dll")]
        public static extern IntPtr CreateCompatibleBitmap(IntPtr hDC, int nWidth, int nHeight);
        [DllImport("gdi32.dll")]
        public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
        [DllImport("gdi32.dll")]
        public static extern bool DeleteDC(IntPtr hDC);
        [DllImport("gdi32.dll")]
        public static extern bool DeleteObject(IntPtr hObject);
        [DllImport("gdi32.dll")]
        public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
        [DllImport("user32.dll")]
        public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
        public const int SRCCOPY = 13369376;

        private Image CaptureImage(IntPtr handle, int posX, int posY, int width, int height)
        {

            IntPtr hdcSrc = GetWindowDC(handle);

            IntPtr hdcDest = CreateCompatibleDC(hdcSrc);
            IntPtr hBitmap = CreateCompatibleBitmap(hdcSrc, width, height);

            IntPtr hOld = SelectObject(hdcDest, hBitmap);
            BitBlt(hdcDest, 0, 0, width, height, hdcSrc, posX, posY, SRCCOPY);
            SelectObject(hdcDest, hOld);
            DeleteDC(hdcDest);
            ReleaseDC(handle, hdcSrc);

            Image image = Image.FromHbitmap(hBitmap);
            DeleteObject(hBitmap);

            return image;
        }

        #endregion

        private void BrowserGame_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            try
            {
                if (this.BrowserGame.IsBusy) return;

                if (Pokerist_BS_Common.GameStatus == Pokerist_BS_Common.GAME_STATUS.PLAY ||
                    Pokerist_BS_Common.GameStatus == Pokerist_BS_Common.GAME_STATUS.PAUSE) return;

                if (this.BrowserGame.Document.GetElementsByTagName("input").GetElementsByName("PokeristSignInForm[login]").Count > 0)
                {
                    grpConfiguration.Enabled = true;
                    Pokerist_BS_Common.GameStatus = Pokerist_BS_Common.GAME_STATUS.LOGIN;

                    SwitchStatusControls();

                    var formLogin = this.BrowserGame.Document.Forms[0];
                    formLogin.GetElementsByTagName("input").GetElementsByName("PokeristSignInForm[login]")[0].InnerText = txtEmail.Text;
                    formLogin.GetElementsByTagName("input").GetElementsByName("PokeristSignInForm[password]")[0].InnerText = txtPassword.Text;
                }
                else if (Pokerist_BS_Common.GameStatus == Pokerist_BS_Common.GAME_STATUS.LOGIN)
                {
                    grpConfiguration.Enabled = false;
                    Pokerist_BS_Common.GameStatus = Pokerist_BS_Common.GAME_STATUS.START;
                    this.BrowserGame.Navigate("http://pokerist.com/en/play-now/");
                }
                else if (Pokerist_BS_Common.GameStatus == Pokerist_BS_Common.GAME_STATUS.START)
                {
                        Thread.Sleep(2000);

                    Pokerist_BS_Common.GameStatus = Pokerist_BS_Common.GAME_STATUS.READY;

                    SwitchStatusControls();

                    //this.BrowserGame.Navigate("http://pokerist.com/profile/game/");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            //AutoItX3 autoit = new AutoItX3();

            ////click call any/ follow button
            //autoit.ControlClick(Pokerist_BS_Common.PokerTitle, "", "[CLASS:Internet Explorer_Server; INSTANCE:1]", "LEFT", 1, Convert.ToInt32(textBox1.Text), Convert.ToInt32(textBox2.Text));

            //autoit = null;

            var image = CaptureImage(this.BrowserGame.Handle, Convert.ToInt32(textBox1.Text), Convert.ToInt32(textBox2.Text),
                Convert.ToInt32(textBox3.Text), Convert.ToInt32(textBox4.Text));

            string path = Path.Combine(Application.StartupPath, @"Data\temp.jpg");

            image.Save(path, System.Drawing.Imaging.ImageFormat.Jpeg);

            image.Dispose();
        }

        private void timerReduceCPU_Tick(object sender, EventArgs e)
        {
            if (Pokerist_BS_Common.TIME_STOP == null) return;
            ResumeThread();
        }
    }
}
